<template>
    <div class="container">
        <div class="left-board">
            <el-scrollbar class="left-scrollbar">
                <div class="components-list">
                    <div v-for="(item, listIndex) in leftComponents" :key="listIndex">
                        <div class="components-title">
                            <vab-icon icon="dashboard-fill"/>
                            {{ item.title }}
                        </div>
                        <draggable
                            class="components-draggable"
                            :list="item.list"
                            :group="{ name: 'componentsGroup', pull: 'clone', put: false }"
                            :clone="cloneComponent"
                            draggable=".components-item"
                            :sort="false"
                            @end="onEnd"
                        >
                            <div
                                v-for="(element, index) in item.list"
                                :key="index"
                                class="components-item"
                                @click="addComponent(element)"
                            >
                                <div class="components-body">
                                    <i :class="element.__config__.tagIcon" style="font-size: 16px"
                                       v-if="isElementIcon(element.__config__.tagIcon)"/>
                                    <vab-icon v-else
                                              :icon="element.__config__.tagIcon"
                                    />
                                    {{ translate(element.__config__.label) }}
                                </div>
                            </div>
                        </draggable>
                    </div>
                </div>
            </el-scrollbar>
        </div>

        <div class="center-board">
            <el-scrollbar class="center-scrollbar">
                <el-row class="center-board-row" :gutter="formConf.gutter">
                    <el-form
                        :size="formConf.size"
                        :label-position="formConf.labelPosition"
                        :disabled="formConf.disabled"
                        :label-width="formConf.labelWidth + 'px'"
                    >
                        <draggable class="drawing-board" :list="drawingList" :animation="340" group="componentsGroup">
                            <draggable-item
                                v-for="(item, index) in drawingList"
                                :key="item.renderKey"
                                :drawing-list="drawingList"
                                :current-item="item"
                                :index="index"
                                :active-id="activeId"
                                :form-conf="formConf"
                                @activeItem="activeFormItem"
                                @copyItem="drawingItemCopy"
                                @deleteItem="drawingItemDelete"
                            />
                        </draggable>
                        <div v-show="!drawingList.length" class="empty-info">
                            {{translate('tips.draggableTip')}}
                        </div>
                    </el-form>
                </el-row>
            </el-scrollbar>
        </div>

        <right-panel
            :active-data="activeData"
            :form-conf="formConf"
            :show-field="drawingList.length > 0 "
            @tag-change="tagChange"
            @fetch-data="fetchData"
        />

        <form-drawer
            :visible.sync="drawerVisible"
            :form-data="formData"
            size="100%"
            :generate-conf="generateConf"
        />
    </div>
</template>
<script lang="ts">
    import Vue from "vue";
    import Component from "vue-class-component";
    import * as _ from 'lodash'
    import {Emit, Prop} from "vue-property-decorator";
    import rightPanel from './right-pannel/right-panel';
    import formDrawer from './form-drawer/form-drawer'
    import {
        InputComponents,LayoutComponents
    } from './consts/const.js';
    import draggable from 'vuedraggable'
    import ComponentListModel from './model/component-list.model';
    import FormConfigModel from "./model/form-config.model";
    import {MoveEvent} from 'vuedraggable'
    import draggableItem from './draggable-item/draggable-item';


    @Component({components: {draggable, draggableItem, rightPanel, formDrawer}})
    export default class FormCreate extends Vue {

        @Prop()
        private data;
        private tempActiveData: any;
        private activeData: any[] = [];
        /**表单配置项*/
        private formConf: FormConfigModel = new FormConfigModel();
        /**拖动组件集合*/
        private drawingList: [] = []
        private idGlobal: number = 1;
        private activeId: number = 0;
        private drawerVisible: boolean = false;
        private jsonDrawerVisible: boolean = false;
        private formData = {};
        private generateConf = null;
        private leftComponents: ComponentListModel[];

        @Emit()
        submitFormJson() {
            return {formConf: this.formConf, fields: this.drawingList}
        }

        private created() {
            this.leftComponents = [
                {
                    title: this.translate('表单组件'),
                    list: InputComponents
                },
                {
                    title: this.translate('布局组件'),
                    list: LayoutComponents
                }];
        }

        private mounted() {


            if (!_.isEmpty(this.data)) {
                this.drawingList = this.data.fields;
                this.formConf = this.data.formConf;
            }
        }

        addComponent(item) {
            const clone = this.cloneComponent(item)
            this.fetchData(clone)
            this.drawingList.push(clone)
            this.activeFormItem(clone)
        }

        activeFormItem(currentItem) {
            this.activeData = currentItem
            this.activeId = currentItem.__config__.formId
        }

        cloneComponent(origin) {
            const clone = _.cloneDeep(origin)
            const config = clone.__config__
            config.span = this.formConf.span // 生成代码时，会根据span做精简判断
            this.createIdAndKey(clone)
            config.label = this.translate(config.label);
            // 输入提示
            if (!_.isEmpty(clone.placeholder)) {
                clone.placeholder = this.translate(clone.placeholder);
            }

            if (!_.isEmpty(config.buttonText)) {
                config.buttonText = this.translate(config.buttonText);
            }

            if (!_.isEmpty(clone.__slot__) && !_.isEmpty(clone.__slot__.options)) {
                clone.__slot__.options.forEach(item => {
                    item.label = this.translate(item.label)
                })
            }

            if (!_.isEmpty(clone.options)) {
                this.translateChild(clone.options)

            }

            if (!_.isEmpty(clone.__slot__) && !_.isEmpty(clone.__slot__.default)) {
                clone.__slot__.default = this.translate(clone.__slot__.default);
            }
            this.tempActiveData = clone
            return this.tempActiveData
        }

        translateChild(item) {
            item.forEach(item => {
                item.label = this.translate(item.label);
                if (!_.isEmpty(item.children)) {
                    this.translateChild(item.children);
                }
            })
        }

        createIdAndKey(item) {
            const config = item.__config__
            config.formId = ++this.idGlobal
            // 改变renderKey后可以实现强制更新组件
            config.renderKey = `${config.formId}${+new Date()}`
            if (config.layout === 'colFormItem') {
                item.__vModel__ = `field${this.idGlobal}`
            } else if (config.layout === 'rowFormItem') {
                config.componentName = `row${this.idGlobal}`
                if (config.children && !_.isArray(config.children) && (config.children.length === 0)) {
                    // rowFormItem无需配置label属性
                    delete config.label
                }
            }
            if (Array.isArray(config.children)) {
                config.children = config.children.map(childItem => this.createIdAndKey(childItem))
            }
            return item
        }

        /**
         * 停止拖动
         * @param obj
         */
        onEnd(obj: MoveEvent<any>) {
            if (obj.from !== obj.to) {
                this.fetchData(this.tempActiveData)
                this.activeData = this.tempActiveData
                this.activeId = this.idGlobal
            }
        }

        drawingItemCopy(item, list) {
            let clone = _.cloneDeep(item);
            clone = this.createIdAndKey(clone)
            list.push(clone)
            this.activeFormItem(clone)
        }

        /**
         * 处理数据
         * @param component
         */
        fetchData(component) {
            const {dataType, method, url} = component.__config__
            console.log(component.__config__)
        }

        /**
         * 删除列表中元素
         * @param index
         * @param list
         */
        drawingItemDelete(index, list) {
            list.splice(index, 1)
            this.$nextTick(() => {
                const len = this.drawingList.length
                if (len) {
                    this.activeFormItem(this.drawingList[len - 1])
                }
            })
        }

        tagChange(newTag) {
            newTag = this.cloneComponent(newTag)
            const config = newTag.__config__
            newTag.__vModel__ = this.activeData['__vModel__']
            config.formId = this.activeId
            config.span = this.activeData['__config__'].span
            this.activeData['__config__'].tag = config.tag
            this.activeData['__config__'].tagIcon = config.tagIcon
            this.activeData['__config__'].document = config.document
            if (typeof this.activeData['__config__'].defaultValue === typeof config.defaultValue) {
                config.defaultValue = this.activeData['__config__'].defaultValue
            }
            Object.keys(newTag).forEach(key => {
                if (this.activeData[key] !== undefined) {
                    newTag[key] = this.activeData[key]
                }
            })
            this.activeData = newTag
            this.updateDrawingList(newTag, this.drawingList)
        }

        updateDrawingList(newTag, list) {
            const index = list.findIndex(item => item.__config__.formId === this.activeId)
            if (index > -1) {
                list.splice(index, 1, newTag)
            } else {
                list.forEach(item => {
                    if (Array.isArray(item.__config__.children)) {
                        this.updateDrawingList(newTag, item.__config__.children)
                    }
                })
            }
        }

        refreshJson(data) {
            this.drawingList = _.cloneDeep(data.fields);
            delete data.fields
            this.formConf = data
        }

        /**
         * 图标是否采用el图标
         */
        get isElementIcon() {
            return (iconName: string): boolean => {
                return iconName.startsWith("el");
            }
        }

        /**
         * 国际化
         */
        get translate() {
            return (key: string, param?: {}): string => {
                return this.$i18n.te(key) ? this.$i18n.t(key, param) as string : key;
            }
        }
    }
</script>
<style lang="scss">
    $selectedColor: #f6f7ff;
    $lighterBlue: #409EFF;

    .container {
        position: relative;
        width: 100%;
        height: 100%;
    }

    .components-list {
        padding: 8px;
        box-sizing: border-box;
        height: 100%;

        .components-item {
            display: inline-block;
            width: 48%;
            margin: 1%;
            transition: transform 0ms !important;
        }
    }

    .components-draggable {
        padding-bottom: 20px;
    }

    .components-title {
        font-size: 14px;
        color: #222;
        margin: 6px 2px;

        .svg-icon {
            color: #666;
            font-size: 18px;
        }
    }

    .components-body {
        padding: 8px 10px;
        background: $selectedColor;
        font-size: 12px;
        cursor: move;
        border: 1px dashed $selectedColor;
        border-radius: 3px;

        .svg-icon {
            color: #777;
            font-size: 15px;
        }

        &:hover {
            border: 1px dashed #787be8;
            color: #787be8;

            .svg-icon {
                color: #787be8;
            }
        }
    }

    .left-board {
        width: 260px;
        position: absolute;
        left: 0;
        top: 0;
        height: 100vh;
    }

    .left-scrollbar {
        height: calc(100vh - 42px);
        overflow: hidden;
    }

    .center-scrollbar {
        height: calc(100vh - 42px);
        overflow: hidden;
        border-left: 1px solid #f1e8e8;
        border-right: 1px solid #f1e8e8;
        box-sizing: border-box;
    }

    .center-board {
        height: 100vh;
        width: auto;
        margin: 0 350px 0 260px;
        box-sizing: border-box;
    }

    .empty-info {
        position: absolute;
        top: 46%;
        left: 0;
        right: 0;
        text-align: center;
        font-size: 18px;
        color: #ccb1ea;
        letter-spacing: 4px;
    }

    .action-bar {
        position: relative;
        height: 42px;
        text-align: right;
        padding: 0 15px;
        box-sizing: border-box;;
        border: 1px solid #f1e8e8;
        border-top: none;
        border-left: none;

        .delete-btn {
            color: #F56C6C;
        }
    }


    .center-board-row {
        padding: 12px 12px 15px 12px;
        box-sizing: border-box;

        & > .el-form {
            // 69 = 12+15+42
            height: calc(100vh - 69px);
        }
    }

    .drawing-board {
        height: 100%;
        position: relative;

        .components-body {
            padding: 0;
            margin: 0;
            font-size: 0;
        }

        .sortable-ghost {
            position: relative;
            display: block;
            overflow: hidden;

            &::before {
                content: " ";
                position: absolute;
                left: 0;
                right: 0;
                top: 0;
                height: 3px;
                background: rgb(89, 89, 223);
                z-index: 2;
            }
        }

        .components-item.sortable-ghost {
            width: 100%;
            height: 60px;
            background-color: $selectedColor;
        }

        .active-from-item {
            & > .el-form-item {
                background: $selectedColor;
                border-radius: 6px;
            }

            & > .drawing-item-copy, & > .drawing-item-delete {
                display: initial;
            }

            & > .component-name {
                color: $lighterBlue;
            }
        }

        .el-form-item {
            margin-bottom: 15px;
        }
    }

    .drawing-item {
        position: relative;
        cursor: move;

        &.unfocus-bordered:not(.active-from-item) > div:first-child {
            border: 1px dashed #ccc;
        }

        .el-form-item {
            padding: 12px 10px;
        }
    }

    .drawing-row-item {
        position: relative;
        cursor: move;
        box-sizing: border-box;
        border: 1px dashed #ccc;
        border-radius: 3px;
        padding: 0 2px;
        margin-bottom: 15px;

        .drawing-row-item {
            margin-bottom: 2px;
        }

        .el-col {
            margin-top: 22px;
        }

        .el-form-item {
            margin-bottom: 0;
        }

        .drag-wrapper {
            min-height: 80px;
        }

        &.active-from-item {
            border: 1px dashed $lighterBlue;
        }

        .component-name {
            position: absolute;
            top: 0;
            left: 0;
            font-size: 12px;
            color: #bbb;
            display: inline-block;
            padding: 0 6px;
        }
    }

    .drawing-item, .drawing-row-item {
        &:hover {
            & > .el-form-item {
                background: $selectedColor;
                border-radius: 6px;
            }

            & > .drawing-item-copy, & > .drawing-item-delete {
                display: initial;
            }
        }

        & > .drawing-item-copy, & > .drawing-item-delete {
            display: none;
            position: absolute;
            top: -10px;
            width: 22px;
            height: 22px;
            line-height: 22px;
            text-align: center;
            border-radius: 50%;
            font-size: 12px;
            border: 1px solid;
            cursor: pointer;
            z-index: 1;
        }

        & > .drawing-item-copy {
            right: 56px;
            border-color: $lighterBlue;
            color: $lighterBlue;
            background: #fff;

            &:hover {
                background: $lighterBlue;
                color: #fff;
            }
        }

        & > .drawing-item-delete {
            right: 24px;
            border-color: #F56C6C;
            color: #F56C6C;
            background: #fff;

            &:hover {
                background: #F56C6C;
                color: #fff;
            }
        }
    }

</style>